<!--
 * @Description: 可配置的实时数据监控图表组件
 * @Version: 2.0
 * @Autor: swc
 * @Date: 2024-09-07 17:12:46
 * @LastEditors: zss
 * @LastEditTime: 2025-09-10 09:26:38
-->
<template>
  <div class="init-container">
    <div class="print-container" ref="printContainer">
      <!-- <Split v-model="split" mode="horizontal">
        <template #left> -->
      <div class="c-base-chart">
        <!-- 添加checkbox选择器 -->
        <div class="header">
          <div class="time-range-picker">
            <TimePicker
              type="timerange"
              format="HH:mm"
              confirm
              v-model="dateTime"
              @on-ok="handleTimeRangeChange('HH:mm')"
              @on-clear="handleTimeRangeChange('HH:mm')"
              placeholder="选择时间范围"
            ></TimePicker>
          </div>
          <div
            class="series-selector"
            v-if="config.data.mapping.series.length > 1"
          >
            <CheckboxGroup v-model="seriesVisibility">
              <Checkbox
                v-for="(series, index) in config.data.mapping.series"
                :key="index"
                :label="index"
                border
              >
                {{ series.name }}
              </Checkbox>
            </CheckboxGroup>
          </div>
          <Button type="primary" @click="print">打印</Button>
        </div>

        <div
          ref="chartContainer"
          class="chart-container"
          :style="{ width: chartWidth, height: chartHeight }"
        ></div>
      </div>
      <!-- </template> -->
      <!-- <template #right>
          <o-base-form :mode="1" ref="bForm"></o-base-form>
        </template>
      </Split> -->
    </div>
    <div class="mask-container" v-if="isMask"></div>
    <div class="error-message" v-if="errorMessage">
      {{ errorMessage }}
    </div>
  </div>
</template>

<script lang="ts">
import * as echarts from 'echarts';
import {
  I_cmd,
  N_cBaseChart,
  T_cmd,
  T_srv,
  Tsrv,
  ifs,
  pLColumns,
  vue
} from './config';

@T_srv.comp
export default class cBaseChart extends vue {
  /* 图表配置 */
  // @T_srv.prop({
  //   required: true,
  //   type: Object,
  //   default: () => ({})
  // })
  // config!: N_cBaseChart.ChartComponentProps['config'];

  public config: N_cBaseChart.ChartComponentProps['config'];

  /* 是否自动初始化 */
  @T_srv.prop({
    required: false,
    type: Boolean,
    default: true
  })
  autoInit!: boolean;

  /* 主题 */
  @T_srv.prop({
    required: false,
    type: String,
    default: ''
  })
  theme!: string;

  /* 父组件compBoxInfo */
  @T_srv.prop({
    required: false,
    type: Object,
    default: null
  })
  compBoxInfo: ifs.I_compBoxInfo;

  /* 组件名 */
  private name: string = 'cBaseChart';

  private funName: string = 'cBaseChart';

  private G_compName: string = this.name;

  /* 组件箱信息对象 */
  private GT_compBoxInfo: ifs.I_compBoxInfo;

  /* 组件箱对象 */
  private GT_compBox: ifs.I_compBox;

  /* 组件箱识别ID */
  private G_compID: string;

  /* 指挥部 */
  private GT_command: I_cmd = new T_cmd();

  /* 遮罩 */
  public isMask: boolean = false;

  /* 错误信息 */
  private errorMessage: string = '';

  /* 系列可见性 */
  private seriesVisibility: number[] = [];

  /* 时间范围选择器 */
  private dateTime: any[] = [null, null];

  private formColumns = pLColumns();

  private split = 0.5;

  /* 计算图表宽度 */
  get chartWidth(): string {
    return this.config?.chart?.width || '100%';
  }

  /* 计算图表高度 */
  get chartHeight(): string {
    return this.config?.chart?.height || '400px';
  }

  /* 监听配置变化 */
  @T_srv.watch('config', { deep: true })
  onConfigChange(newConfig: N_cBaseChart.ChartComponentProps['config']) {
    if (this.GT_command) {
      // 重新初始化图表
      this.initChart();
    }
  }

  // /* 监听系列可见性变化 */
  @T_srv.watch('seriesVisibility', { deep: true })
  onSeriesVisibilityChange() {
    if (this.GT_command) {
      // 将索引数组转换为布尔数组传递给命令类
      const visibility = this.config.data.mapping.series.map((_, index) =>
        this.seriesVisibility.includes(index)
      );
      this.GT_command.setSeriesVisibility(visibility);
    }
  }

  created() {
    // 如果父组件没有传参，那就产生一个
    this.GT_compBoxInfo = Tsrv.getCompInfo(this.compBoxInfo);
    this.G_compID = this.GT_compBoxInfo.compID;
    this.GT_compBox = this.GT_compBoxInfo.TcompBox;
    this.GT_command.init(this, this.GT_compBoxInfo);

    this.config = this.GT_command.chartConfig;

    // 初始化所有系列为可见状态
    this.seriesVisibility = this.config.data.mapping.series.map(
      (_, index) => index
    );

    // 初始化时间范围选择器
    this.dateTime = this.getDefaultRange();
  }

  mounted() {
    /* 向父组件发送实例 */
    this.GT_compBox.addCompMergeName(this.G_compID, this.G_compName, this);
    this.$emit('compBoxInfo', this.GT_compBoxInfo);
    // 如果配置了自动初始化，则在挂载后初始化图表
    if (this.autoInit) {
      this.$nextTick(() => {
        this.initChart();
      });
    }

    this.handleTimeRangeChange('YYYY-MM-DD HH:mm:ss');
    setTimeout(() => {
      this.loadForm();
    }, 1000);
  }

  destroyed() {
    // 销毁图表实例
    this.dispose();

    /* 注册组件销毁 */
    this.GT_compBox.removeCompMergeName(this.G_compID, this.G_compName);

    /* 如果父组件传入的compBoxInfo则删除本文件产生的引用,反之是本组件产生的ID统一删除 */
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox.removeCompsWithCompID(this.G_compID);
    } else {
      this.GT_compBox.removeCompsMergeName(this.G_compID, [
        `'${this.G_compName}'`
      ]);
    }
  }

  private loadForm() {
    const form: any = this.$refs['bForm'];
    const formCol = form.transformColumns(this.formColumns);
    form.setColumns(formCol);
    // form.setFormData(this.formData);
    form.setModify(false);
  }

  /* 获取默认时间范围 */
  private getDefaultRange(): [Date, Date] {
    const end = new Date();
    const start = new Date(end.getTime() - 600000);
    return [start, end];
  }

  /* 设置组件整体遮罩 */
  public setMask(p: boolean) {
    this.isMask = p;
  }

  public getMask(p: boolean): boolean {
    return this.isMask;
  }

  /* 初始化图表 */
  public initChart(): void {
    try {
      this.errorMessage = '';
      (this.GT_command as any).initChart();
    } catch (error) {
      console.error('初始化图表失败:', error);
      this.errorMessage = '图表初始化失败';
    }
  }

  /* 手动更新数据 */
  public updateData(data: any): void {
    try {
      (this.GT_command as any).updateData(data);
    } catch (error) {
      console.error('更新数据失败:', error);
    }
  }

  /* 刷新图表 */
  public refresh(): void {
    try {
      (this.GT_command as any).refresh();
    } catch (error) {
      console.error('刷新图表失败:', error);
    }
  }

  /* 调整尺寸 */
  public resize(): void {
    try {
      (this.GT_command as any).resize();
    } catch (error) {
      console.error('调整尺寸失败:', error);
    }
  }

  /* 销毁图表 */
  public dispose(): void {
    try {
      (this.GT_command as any).dispose();
    } catch (error) {
      console.error('销毁图表失败:', error);
    }
  }

  /* 获取ECharts实例 */
  public getInstance(): echarts.ECharts | null {
    try {
      // 直接访问command类的chartInstance属性
      return this.GT_command.chartInstance;
    } catch (error) {
      console.error('获取实例失败:', error);
      return null;
    }
  }

  // 打印
  private async print() {
    try {
      // 获取图表实例并转换为图片
      const chartInstance = this.getInstance();
      let chartImage = '';

      if (chartInstance) {
        // 等待图表渲染完成
        await new Promise(resolve => setTimeout(resolve, 300));

        try {
          chartImage = chartInstance.getDataURL({
            type: 'png',
            pixelRatio: 2,
            backgroundColor: '#fff'
          });
        } catch (error) {
          console.error('图表截图失败:', error);
        }
      } else {
        console.warn('图表实例不存在，请确保图表已初始化');
      }

      // 获取表单的当前状态
      let formHtml = '';
      const formContainer = this.$el.querySelector('.form-panel');

      if (formContainer) {
        // 创建一个临时的div来获取表单的当前状态
        const tempDiv = document.createElement('div');

        // 复制表单元素及其所有子元素
        const formClone = formContainer.cloneNode(true) as HTMLElement;

        // 获取所有输入框的值并设置到克隆的表单中
        const inputs = formContainer.querySelectorAll('input');
        const cloneInputs = formClone.querySelectorAll('input');

        inputs.forEach((input, index) => {
          if (cloneInputs[index]) {
            cloneInputs[index].setAttribute('value', input.value);
          }
        });

        tempDiv.appendChild(formClone);
        formHtml = tempDiv.innerHTML;
      }

      // 创建打印窗口
      const printWindow = window.open('', '_blank', 'width=800,height=600');
      if (!printWindow) {
        console.error('无法打开打印窗口，请检查浏览器弹窗设置');
        return;
      }

      // 写入打印内容
      printWindow.document.write(`
        <!DOCTYPE html>
        <html>
          <head>
            <title>图表打印</title>
            <style>
              body { 
                margin: 0; 
                padding: 20px; 
                font-family: Arial, sans-serif;
              }
              .chart-image { 
                max-width: 100%; 
                margin-bottom: 20px;
                display: block;
              }
              .form-container { 
                width: 100%; 
                padding: 20px;
                border: 1px solid #ddd;
                border-radius: 5px;
              }
              .form-container .ivu-form-item {
                margin-bottom: 16px;
              }
              .form-container .ivu-input {
                width: 100%;
                padding: 8px;
                border: 1px solid #ddd;
                border-radius: 3px;
              }
              @media print {
                body { margin: 0; padding: 10px; }
                .chart-image, .form-container { 
                  page-break-inside: avoid; 
                }
                .form-container {
                  border: none;
                  padding: 10px;
                }
              }
            </style>
          </head>
          <body>
            ${
              chartImage
                ? `<img src="${chartImage}" class="chart-image">`
                : '<div style="color: red; margin-bottom: 20px;">图表未加载</div>'
            }
            ${
              formHtml
                ? `<div class="form-container">${formHtml}</div>`
                : '<div style="color: red;">表单未找到</div>'
            }
          </body>
        </html>
      `);

      printWindow.document.close();

      // 等待内容加载完成后打印
      printWindow.onload = function() {
        printWindow.focus();
        printWindow.print();
      };
    } catch (error) {
      console.error('打印失败:', error);
    }
  }

  // 时间选择
  private async handleTimeRangeChange(dateType: string) {
    try {
      if (!this.dateTime[0] || !this.dateTime[1]) return;

      let [start, end] = ['', ''];
      if (dateType === 'YYYY-MM-DD HH:mm:ss') {
        start = new Date(
          this.formatDateTime(this.dateTime[0])
        ).toLocaleString();
        end = new Date(this.formatDateTime(this.dateTime[1])).toLocaleString();
      } else {
        start = new Date(
          this.formatDateTime(this.dateTime[0], 'time')
        ).toLocaleString();
        end = new Date(
          this.formatDateTime(this.dateTime[1], 'time')
        ).toLocaleString();
      }

      const codes = this.seriesVisibility.map(
        item => this.config.data.mapping.series[item].code
      );
      const params: ifs.I_qryDataReq = {
        ecCodes: codes,
        beginTime: start,
        endTime: end,
        pageNo: 1,
        pageSize: 999
      };

      const res = await Tsrv.getQueryData(params);
      if (typeof res === 'boolean' || Tsrv.noValue(res)) return;

      // 使用降采样处理数据
      this.GT_command.chartData = this.GT_command.chartData.map(item => {
        if (!res[item.code] || res[item.code].d.length === 0) return item;

        // 对原始数据进行降采样处理，采样间隔1分钟（60000毫秒）
        const sampledData = this.GT_command.downsampleData(
          res[item.code].d,
          60000
        );

        return {
          ...item,
          values: sampledData
        };
      });

      this.GT_command.updateChartOptions();
    } catch (error) {
      console.error('获取数据失败:', error);
    }
  }

  // 时间格式化
  private formatDateTime(
    input: string | Date,
    dateType: 'time' | 'iso' = 'iso'
  ) {
    let date: Date;

    if (dateType === 'time') {
      const [hours, minutes] = (input as string).split(':').map(Number);
      date = new Date();
      date.setHours(hours, minutes, 0, 0);
    } else {
      date = new Date(input);
    }

    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');

    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  }
}
</script>

<style lang="scss" scoped>
@media print {
  body * {
    display: none !important;
  }
  .print-container,
  .print-container * {
    display: block !important;
    visibility: visible !important;
  }
  .print-container {
    position: static;
    width: 100%;
    height: auto;
  }
}

.c-base-chart {
  position: relative;
  width: 100%;
  height: 100%;

  .header {
    display: flex;
    justify-content: start;
    align-items: center;
    padding: 16px;
  }

  .series-selector {
    // margin-bottom: 16px;
    // padding: 12px;
    margin: 0 5px;
    background-color: #f8f8f9;
    border-radius: 4px;
    border: 1px solid #e8eaec;

    .ivu-checkbox-group {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
    }

    .ivu-checkbox-wrapper {
      margin-right: 0;
      font-size: 14px;

      &:hover {
        color: #2d8cf0;
      }
    }
  }

  .chart-container {
    width: 100%;
    height: calc(100% - 60px); /* 为选择器留出空间 */
  }

  .mask-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(255, 255, 255, 0.7);
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .error-message {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: #f56c6c;
    background-color: #fef0f0;
    padding: 10px 20px;
    border-radius: 4px;
    border: 1px solid #fbc4c4;
    z-index: 20;
  }
}
</style>
